<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Detect Indirect Calls Stage</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Detect Indirect Calls Stage' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../intern.html">Inter Modules</a></li><li><a href="index.html">pipeline</a></li><li><a href="index.html#4">Chapter 4: Linking</a></li><li><b>Detect Indirect Calls Stage</b></li></ul></div>
<p class="purpose">To handle function calls made to functions identified by symbols which turn out, during linking, to be variables rather than constants.</p>

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. </b>Suppose kit A makes the function call <span class="extract"><span class="extract-syntax">Mystery(1, 2, 3)</span></span>, where <span class="extract"><span class="extract-syntax">Mystery</span></span> is a
function defined in kit B; and suppose further that <span class="extract"><span class="extract-syntax">Mystery</span></span> is not the name of
a function, but the name of a variable in kit B, whose value at runtime will be
the address of the function which must be called. The original call in Kit A
will be a function invocation like so:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> Mystery</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> </span><span class="constant-syntax">3</span>
</pre>
<p class="commentary">But this is incorrect, because only explicitly identified functions can be
invoked like this, and <span class="extract"><span class="extract-syntax">Mystery</span></span> turns out to be a variable. (The compiler
of kit A has no way to know this.) We must correct to:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">inv</span><span class="plain-syntax"> </span><span class="function-syntax">!indirect3v</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_unchecked</span><span class="plain-syntax"> Mystery</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">val</span><span class="plain-syntax"> </span><span class="identifier-syntax">K_number</span><span class="plain-syntax"> </span><span class="constant-syntax">3</span>
</pre>
<p class="commentary">This looks like an edge case, and it would certainly be possible to rewrite the
kits so that it doesn't arise. But rejecting such usages with an error message
would be as slow as correcting them, so we might as well get them right.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">DetectIndirectCallsStage::create_pipeline_stage</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">DetectIndirectCallsStage::create_pipeline_stage</span></span>:<br/>Parsing Pipelines - <a href="2-pp.html#SP10">&#167;10</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><a href="2-pp.html#SP3" class="function-link"><span class="function-syntax">ParsingPipelines::new_stage</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">I</span><span class="string-syntax">"detect-indirect-calls"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><a href="4-dics.html#SP1" class="function-link"><span class="function-syntax">DetectIndirectCallsStage::run</span></a><span class="plain-syntax">, </span><span class="constant-syntax">NO_STAGE_ARG</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">DetectIndirectCallsStage::run</span><span class="plain-syntax">(</span><span class="reserved-syntax">pipeline_step</span><span class="plain-syntax"> *</span><span class="identifier-syntax">step</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">InterTree::traverse</span><span class="plain-syntax">(</span><span class="identifier-syntax">step</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ephemera</span><span class="plain-syntax">.</span><span class="element-syntax">tree</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><a href="4-dics.html#SP1" class="function-link"><span class="function-syntax">DetectIndirectCallsStage::visitor</span></a><span class="plain-syntax">, </span><span class="identifier-syntax">step</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">PACKAGE_IST</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">DetectIndirectCallsStage::visitor</span><span class="plain-syntax">(</span><span class="identifier-syntax">inter_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">I</span><span class="plain-syntax">, </span><span class="identifier-syntax">inter_tree_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">state</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">pipeline_step</span><span class="plain-syntax"> *</span><span class="identifier-syntax">step</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">pipeline_step</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">state</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">inter_package</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pack</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PackageInstruction::at_this_head</span><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">InterPackage::is_a_function_body</span><span class="plain-syntax">(</span><span class="identifier-syntax">pack</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">inter_tree_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">D</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InterPackage::head</span><span class="plain-syntax">(</span><span class="identifier-syntax">pack</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><a href="4-dics.html#SP2" class="function-link"><span class="function-syntax">DetectIndirectCallsStage::traverse_code_tree</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">D</span><span class="plain-syntax">, </span><span class="identifier-syntax">step</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>Within each code package (i.e., function body), we make a depth-first traverse,
though as it happens this transformation would work just as well either way:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">DetectIndirectCallsStage::traverse_code_tree</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">DetectIndirectCallsStage::traverse_code_tree</span></span>:<br/><a href="4-dics.html#SP1">&#167;1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">inter_tree_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="reserved-syntax">pipeline_step</span><span class="plain-syntax"> *</span><span class="identifier-syntax">step</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">PROTECTED_LOOP_THROUGH_INTER_CHILDREN</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">P</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><a href="4-dics.html#SP2" class="function-link"><span class="function-syntax">DetectIndirectCallsStage::traverse_code_tree</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">step</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">PROTECTED_LOOP_THROUGH_INTER_CHILDREN</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">P</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Inode::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">INV_IST</span><span class="plain-syntax">)) &amp;&amp;</span>
<span class="plain-syntax">            (</span><span class="identifier-syntax">InvInstruction::method</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FUNCTION_INVMETH</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">inter_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InvInstruction::function</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">var</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"bad invocation"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">inter_tree_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">D</span><span class="plain-syntax"> = </span><span class="identifier-syntax">var</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">definition</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Inode::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">D</span><span class="plain-syntax">, </span><span class="identifier-syntax">VARIABLE_IST</span><span class="plain-syntax">))</span>
<span class="plain-syntax">                </span><span class="named-paragraph-container code-font"><a href="4-dics.html#SP2_1" class="named-paragraph-link"><span class="named-paragraph">This is an invocation of a variable not a function</span><span class="named-paragraph-number">2.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2_1" class="paragraph-anchor"></a><b>&#167;2.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">This is an invocation of a variable not a function</span><span class="named-paragraph-number">2.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">inter_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">I</span><span class="plain-syntax"> = </span><span class="identifier-syntax">F</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">tree</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="4-dics.html#SP2_1_1" class="named-paragraph-link"><span class="named-paragraph">Change to be an invocation of a primitive</span><span class="named-paragraph-number">2.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="4-dics.html#SP2_1_2" class="named-paragraph-link"><span class="named-paragraph">Insert the variable as the new first argument</span><span class="named-paragraph-number">2.1.2</span></a></span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-dics.html#SP2">&#167;2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP2_1_1" class="paragraph-anchor"></a><b>&#167;2.1.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Change to be an invocation of a primitive</span><span class="named-paragraph-number">2.1.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">arity</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_THROUGH_INTER_CHILDREN</span><span class="plain-syntax">(</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">F</span><span class="plain-syntax">) </span><span class="identifier-syntax">arity</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">inter_ti</span><span class="plain-syntax"> </span><span class="identifier-syntax">prim</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Primitives::BIP_for_indirect_call_returning_value</span><span class="plain-syntax">(</span><span class="identifier-syntax">arity</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">inter_symbol</span><span class="plain-syntax"> *</span><span class="identifier-syntax">prim_s</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Primitives::from_BIP</span><span class="plain-syntax">(</span><span class="identifier-syntax">I</span><span class="plain-syntax">, </span><span class="identifier-syntax">prim</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">InvInstruction::write_primitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">I</span><span class="plain-syntax">, </span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">prim_s</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-dics.html#SP2_1">&#167;2.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP2_1_2" class="paragraph-anchor"></a><b>&#167;2.1.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Insert the variable as the new first argument</span><span class="named-paragraph-number">2.1.2</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">inter_bookmark</span><span class="plain-syntax"> </span><span class="identifier-syntax">IBM</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InterBookmark::first_child_of</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">inter_pair</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InterValuePairs::symbolic</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">IBM</span><span class="plain-syntax">, </span><span class="identifier-syntax">var</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">ValInstruction::new</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">IBM</span><span class="plain-syntax">, </span><span class="identifier-syntax">InterTypes::unchecked</span><span class="plain-syntax">(), </span><span class="identifier-syntax">Inode::get_level</span><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">) + </span><span class="constant-syntax">1</span><span class="plain-syntax">, </span><span class="identifier-syntax">val</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-dics.html#SP2_1">&#167;2.1</a>.</li></ul>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="4-sws.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-pm.html">1</a></li><li class="progresschapter"><a href="2-pp.html">2</a></li><li class="progresschapter"><a href="3-ps.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-lbks.html">lbks</a></li><li class="progresssection"><a href="4-sws.html">sws</a></li><li class="progresscurrent">dics</li><li class="progresssection"><a href="4-mius.html">mius</a></li><li class="progresssection"><a href="4-rvs.html">rvs</a></li><li class="progresssection"><a href="4-tsk.html">tsk</a></li><li class="progresschapter"><a href="5-msms.html">5</a></li><li class="progresschapter"><a href="6-erms.html">6</a></li><li class="progressnext"><a href="4-mius.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

